package com.xhl.common.util;

import cn.hutool.crypto.SecureUtil;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;


/**
 * RSA 非对称算法工具
 * 在线生成公私密钥  https://www.bejson.com/enc/rsa/
 * https://www.cnblogs.com/undefined22/p/12651361.html
 * @Author CazCen
 * @Date 2021/11/29 15:32
 */
public class MakeRSAUtil {

    private static final Logger logger = LoggerFactory.getLogger(MakeRSAUtil.class);

    private static final String RSA_ALGORITHM = "RSA";

    /**
     * 生成私密
     *
     * PKCS #8: Private-Key Information Syntax Standard
     * PKCS #8 跟公钥没啥关系，公钥格式定义可参考相关文档。
     *
     * @param key 需要满足 PKCS #8 格式
     * @return PrivateKey
     */
    public static PrivateKey getPrivateKey(byte[] key){

        PrivateKey rsa = SecureUtil.generatePrivateKey(RSA_ALGORITHM, key);

        return rsa;
    }

    /**
     * 生成私密
     * PKCS #8: Private-Key Information Syntax Standard
     * PKCS #8 跟公钥没啥关系，公钥格式定义可参考相关文档。
     *
     * @param key 需要满足 PKCS #8 格式
     * @return byte[]
     */
    public static byte[] getPrivateKeyEncoded(byte[] key){

        PrivateKey rsa = SecureUtil.generatePrivateKey(RSA_ALGORITHM, key);

        logger.info("getPrivateKeyEncoded getFormat {}",rsa.getFormat());

        byte[] encoded = rsa.getEncoded();
        return encoded;
    }

    /**
     * 生成公钥
     * key – 密钥，必须为DER编码存储
     * @return PublicKey
     */
    public static PublicKey getPublicKey(byte[] key){

        PublicKey rsa = SecureUtil.generatePublicKey(RSA_ALGORITHM, key);

        return rsa;
    }


    /**
     * 生成公钥
     * @param key
     * key – 密钥，必须为DER编码存储
     * @return byte[]
     */
    public static byte[] getPublicKeyEncoded(byte[] key){

        PublicKey rsa = SecureUtil.generatePublicKey(RSA_ALGORITHM, key);

        byte[] encoded = rsa.getEncoded();

        return encoded;
    }

    /**
     * 生成秘钥对
     * @param
     *
     * @return KeyPair
     */
    public static KeyPair getKeyPair(){

        KeyPair keyPair = SecureUtil.generateKeyPair(RSA_ALGORITHM);

        return keyPair;
    }


    /**
     * 私钥加密
     * @param data 待加密数据
     * @param key 密钥
     * @return byte[] 加密数据
     * */
    public static byte[] encryptByPrivateKey(byte[] data,byte[] key) throws Exception{

        //取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory= KeyFactory.getInstance(RSA_ALGORITHM);
        //生成私钥
        PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);
        //数据加密
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }

    /**
     * 公钥加密
     * @param data
     * @param key
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeySpecException
     * @throws NoSuchPaddingException
     * @throws BadPaddingException
     * @throws IllegalBlockSizeException
     * @throws InvalidKeyException
     */
    public static byte[] encryptByPublicKey(byte[] data, byte[] key) throws NoSuchAlgorithmException,
            InvalidKeySpecException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException {
        //实例化密钥工厂
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        //初始化公钥,根据给定的编码密钥创建一个新的 X509EncodedKeySpec。
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
        PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
        //数据加密
        Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.ENCRYPT_MODE,publicKey);
        return cipher.doFinal(data);
    }

    /**
     * 私钥解密
     * @param data 待解密数据
     * @param key 密钥
     * @return byte[] 解密数据
     * */
    public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception{
        //取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec=new PKCS8EncodedKeySpec(key);
        KeyFactory keyFactory=KeyFactory.getInstance(RSA_ALGORITHM);
        //生成私钥
        PrivateKey privateKey=keyFactory.generatePrivate(pkcs8KeySpec);
        //数据解密
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(data);
    }


    /**
     * 公钥解密
     * @param data 待解密数据
     * @param key 密钥
     * @return byte[] 解密数据
     * */
    public static byte[] decryptByPublicKey(byte[] data,byte[] key) throws Exception{

        //实例化密钥工厂
        KeyFactory keyFactory=KeyFactory.getInstance(RSA_ALGORITHM);
        //初始化公钥
        //密钥材料转换
        X509EncodedKeySpec x509KeySpec=new X509EncodedKeySpec(key);
        //产生公钥
        PublicKey pubKey=keyFactory.generatePublic(x509KeySpec);
        //数据解密
        Cipher cipher=Cipher.getInstance(keyFactory.getAlgorithm());
        cipher.init(Cipher.DECRYPT_MODE, pubKey);
        return cipher.doFinal(data);
    }


}
